<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>命令模式（Command Pattern）</title>
    <!-- 
    命令模式（Command Pattern）是一种行为型设计模式，它将请求封装为一个对象，从而使得可以用不同的请求对客户进行参数化、排队请求、记录请求日志，以及支持可撤销的操作。命令模式涉及到四个主要角色：

    ### 主要组成部分

    1. **命令接口（Command）**：声明执行操作的接口。
    2. **具体命令（Concrete Command）**：实现命令接口，定义与接收者之间的绑定关系，并调用接收者的相应操作。
    3. **接收者（Receiver）**：知道如何实施与执行一个请求相关的操作，具体实现请求的业务逻辑。
    4. **调用者（Invoker）**：要求执行命令的对象，通常会持有命令对象的引用，并在适当的时候调用命令的执行方法。

    ### 命令模式的优点

    1. **解耦**：命令模式将请求的发送者和接收者解耦，使得两者之间的关系更加灵活。
    2. **支持撤销操作**：通过命令对象，可以轻松实现操作的撤销和重做。
    3. **支持日志记录**：可以记录命令的执行历史，便于调试和审计。
    4. **参数化请求**：可以使用不同的命令对象来参数化请求。

    ### 命令模式的缺点

    1. **增加系统复杂性**：命令模式引入了多个类，可能会使系统结构变得复杂。
    2. **不适合简单操作**：对于简单的操作，使用命令模式可能会显得过于繁琐。

    ### 示例代码

    以下是一个使用命令模式的简单示例，展示如何实现一个简单的遥控器系统。

    #### 1. 命令接口（Command）

    ```javascript
    class Command {
        execute() {
            throw new Error("此方法必须被实现。");
        }
    }
    ```

    #### 2. 接收者（Receiver）

    ```javascript
    class Light {
        on() {
            console.log("灯已打开。");
        }

        off() {
            console.log("灯已关闭。");
        }
    }
    ```

    #### 3. 具体命令（Concrete Command）

    ```javascript
    class LightOnCommand extends Command {
        constructor(light) {
            super();
            this.light = light;
        }

        execute() {
            this.light.on();
        }
    }

    class LightOffCommand extends Command {
        constructor(light) {
            super();
            this.light = light;
        }

        execute() {
            this.light.off();
        }
    }
    ```

    #### 4. 调用者（Invoker）

    ```javascript
    class RemoteControl {
        constructor() {
            this.command = null;
        }

        setCommand(command) {
            this.command = command;
        }

        pressButton() {
            this.command.execute();
        }
    }
    ```

    #### 5. 使用示例

    ```javascript
    const light = new Light();
    const lightOn = new LightOnCommand(light);
    const lightOff = new LightOffCommand(light);

    const remote = new RemoteControl();

    remote.setCommand(lightOn);
    remote.pressButton(); // 输出: "灯已打开。"

    remote.setCommand(lightOff);
    remote.pressButton(); // 输出: "灯已关闭。"
    ```

    ### 总结

    命令模式是一种灵活且强大的设计模式，适用于需要将请求封装为对象的场景。通过将请求的发送者与接收者解耦，命令模式提高了系统的可扩展性和可维护性。在设计系统时，合理运用命令模式可以简化请求的处理逻辑，增强系统的灵活性。
    -->
  </head>
  <body>
    <script>
      // 命令模式是一种灵活且强大的设计模式，适用于需要将请求封装为对象的场景。通过将请求的发送者与接收者解耦，命令模式提高了系统的可扩展性和可维护性。在设计系统时，合理运用命令模式可以简化请求的处理逻辑，增强系统的灵活性。

      class Command {
        execute() {
          throw new Error("此方法必须被实现。");
        }
      }

      class Light {
        on() {
          console.log("灯已打开。");
        }

        off() {
          console.log("灯已关闭。");
        }
      }

      class LightOnCommand extends Command {
        constructor(light) {
          super();
          this.light = light;
        }

        execute() {
          this.light.on();
        }
      }

      class LightOffCommand extends Command {
        constructor(light) {
          super();
          this.light = light;
        }

        execute() {
          this.light.off();
        }
      }

      class RemoteControl {
        constructor() {
          this.command = null;
        }

        setCommand(command) {
          this.command = command;
        }

        pressButton() {
          this.command.execute();
        }
      }

      function Light() {
        let light = new Light();
        let lightOn = new LightOnCommand(light);
        let lightOff = new LightOffCommand(light);

        let remote = new RemoteControl(); // 遥控器
        remote.setCommand(lightOn);
        remote.pressButton(); // 打开灯
        remote.setCommand(lightOff);
        remote.pressButton(); // 关闭灯
        remote.setCommand(lightOn);
        remote.pressButton(); // 打开灯
      }

      Light();
    </script>
  </body>
</html>
